import { _decorator, Component, Node, Label, find, Vec3, Vec2, dragonBones, systemEvent, SystemEventType, EventKeyboard, macro, tween, SystemEvent, director } from 'cc';
const { ccclass, property } = _decorator;

const ANI_GROUP = "normal";
//攻击动画
const ATTANILIST = ["att_1", "att_2", "att_3", "att_4"];

var SKINLIST = ['p_fist', 'p_sword'];
// 对象名必须与文件一致
import { Common } from './common';
// 实例化
const COM = new Common();

@ccclass('Hero')
export class Hero extends Component {
	// [1]
	// dummy = '';
	private _curPos: Vec3 = new Vec3();
	private _curPos_enemy: Vec3 = new Vec3();

	private _curCameraPos: Vec3 = new Vec3();
	private _curScale: Vec3 = new Vec3();
	// [2]
	// @property
	// serializableDummy = 0;
	// private	faceDirection=1

	// 在元素里定义变量，用来绑定控件
	@property({ type: Node })
	leftButton = null;
	@property({ type: Node })
	rightButton = null;
	@property({ type: Node })
	hpBar = null;

	@property({ type: Node })
	blackNode = null;


	@property({ type: Node })
	changeWepButton = null;



	//  @property({type: SkeletalAnimation})
	//    public CocosAnim: SkeletalAnimation|null = null;



	start() {
		// [3]


		// this.node.getChildByName
		// 获取子节点的龙骨
		this.dbDisplay = this.node.getChildByName("body").getComponent(dragonBones.ArmatureDisplay);
		// 动画
		this.dbArmature = this.dbDisplay.armature();
		//当前职业是剑，
		this.defSkinId = 1;

		//获得武器的龙骨动画组件
		this.wepDisplay = this.node.parent.parent.getChildByName("sword").getComponent(dragonBones.ArmatureDisplay);

		//先把主角的节点排序设高一点点
		//不改之前，主角是在敌人的下面
		this.node.zIndex = 2;
		this.node.isDie = false;
		this._speed = 0; //当前行走速度
		this.moveSpeed = 20; //行走速度
		this._faceDir = 1; //脸部朝向 1是左边，-1是右边
		this.node._State = Common.State.IDLE; //把当前状态设为待机
		this._onButton = false;//是否按着BUTTON
		//在主角的组件时，获取game的组件
		this.game = this.node.parent.getComponent("Game");

		// this.game.showHit(123,new Vec3(0,0,0))
		//先绑定一个敌人
		//当前节点的父节点下，名为enemy的节点
		//获得game组件上的boundary
		this.boundary = Common.boundary;
		this.attCount = 0; //当前攻击动画的序号
		//设定角色的碰撞范围
		//这个cW我是乱命名的，给当前节点添加一个属性
		//x就是宽度，y是高度,当前节点的宽度/2，就是碰撞的距离，角色的00位置在中间所以要除于2
		//而高度为什么不除2呢，因为角色的高度锚点在底部
		this.node.cW = { x: this.node.width / 2, y: this.node.height };
		//添加龙骨动画，播放完毕的监听事件

		this.dbDisplay.on(dragonBones.EventObject.COMPLETE, this.aniComplete, this);

		//添加一个动画帧事件
		this.dbDisplay.on(dragonBones.EventObject.FRAME_EVENT, this.frameEvent, this);

		this.enemyList = this.game.allEnemy;


		this.setEvent(this.leftButton);
		this.setEvent(this.rightButton);

		this.setKeyBoard();

		//初始化角色
		//主角的属性
		this.node.ROLE = this.ROLE = {
			att: 30,
			wepId: 0,//当前武器ID
			hp: 100,
			totalHp: 100,//总体力
			dodgeLen: 200, //回避距离
			dodgeSpeed: 20, //
			hpW: this.hpBar.width,
			score: 0
		}

		this.idleAni();
		this.updateWep();
		//接下来，我们要绑定按钮的事件
		//接下来，开始角色的移动


	}





	//换职业
	changeSkin() {
		console.log("换职业")
		//切换职业ID
		//如果当前职业ID，小于职业数量，即+1,否即等于0
		if (this.node.isDie) return;
		this.defSkinId = this.defSkinId < SKINLIST.length - 1 ? this.defSkinId + 1 : 0;
		if (this.defSkinId != 1)
			this.changeWepButton.active = false;
		else
			this.changeWepButton.active = true;
		let skinName = SKINLIST[this.defSkinId];//当前即职名称
		this.dbDisplay.armatureName = skinName;
		this.dbArmature = this.dbDisplay.armature();
		this.updateWep();
	}

	//换武器
	changeWep() {
		//判断当前职业是否可以换武器
		//只有下标为1的职业才能换武器
		if (this.defSkinId != 1 || this.node.isDie) return;
		//随机一个武器的ID，这里有20把武器
		let wepId = Math.floor(Math.random() * 20);
		this.ROLE.wepId = wepId;
		this.updateWep();
	}

	//更新武器
	updateWep() {
		if (this.defSkinId != 1) return;
		//取的武器的armature
		let wep = this.wepDisplay.buildArmature("s_" + this.ROLE.wepId);
		//替换主角的武器
		//这个sword武器的插槽
		this.dbArmature.getSlot("sword").childArmature = wep.armature();
	}

	//有什么不明白，可以在B站上给我留言，这个没有话筒，很多知识都不能说的好详细。
	//以后在教程里，再慢慢的解释
	//下一集再见
	aniComplete(e) {
		//cc.log(e.animationState.name);
		//如果播放完动画，即继续播放攻击动画
		//今天就做到这吧，下次再接着做下一部份
		//当攻击动画播放完时，判断是否按着按钮，如果不是按着即播放待机画面
		if (this.node.isDie) return;
		let enemy = this.getEnemy();
		if (this._onButton && Common.checkCollide(this.node, enemy)) {
			this.attackAni();
		} else {
			this.idleAni();
		}
	}

	frameEvent(e) {
		//我在龙骨动画里，设定了一个攻击的帧事件，叫attack
		if (this.node.isDie) return;
		if (e.name == "attack") {
			//如果在击的帧事件时，碰撞到敌，即敌人造成伤害
			let enemy = this.getEnemy();
			if (Common.checkCollide(this.node, enemy, 50)) {
				enemy.getComponent("Enemy").uatt(this.ROLE.att);
			}
		}
	}

	setKeyBoard(on = true) {
		if (on) {
			systemEvent.on(SystemEventType.KEY_DOWN, this.keydown, this);
			systemEvent.on(SystemEventType.KEY_UP, this.keyup, this)
		} else {
			systemEvent.off(SystemEventType.KEY_DOWN, this.keydown, this);
			systemEvent.off(SystemEventType.KEY_UP, this.keyup, this)
		}

	}

	keydown(e) {
		switch (e.keyCode) {
			case macro.KEY.left:
				this.touchStart({ 'target': { 'name': 'left' } })
				break;
			case macro.KEY.right:
				this.touchStart({ 'target': { 'name': 'right' } })
				break;
			case macro.KEY.a:
				this.touchStart({ 'target': { 'name': 'left' } })
				break;
			case macro.KEY.d:
				this.touchStart({ 'target': { 'name': 'right' } })
				break;
			default:
				break;
		}

	}
	keyup(e) {
		switch (e.keyCode) {
			case macro.KEY.left:
				this.touchEnd(e)
				break;
			case macro.KEY.right:
				this.touchEnd(e)
				break;
			case macro.KEY.a:
				this.touchEnd(e)
				break;
			case macro.KEY.d:
				this.touchEnd(e)
				break;
			default:
				break;
		}

	}
	setEvent(node) {
		//按钮的触摸事件，触摸开始
		node.on(SystemEvent.EventType.TOUCH_START, this.touchStart, this);
		//触摸结束
		node.on(SystemEvent.EventType.TOUCH_END, this.touchEnd, this);
		node.on(SystemEvent.EventType.TOUCH_CANCEL, this.touchEnd, this);



	}

	offEvent(node) {
		//按钮的触摸事件，触摸开始
		node.off(SystemEvent.EventType.TOUCH_START, this.touchStart, this);
		//触摸结束
		node.off(SystemEvent.EventType.TOUCH_END, this.touchEnd, this);
		node.off(SystemEvent.EventType.TOUCH_CANCEL, this.touchEnd, this);
	}

	//触摸开始
	touchStart(e) {
		// console.log(e)
		//如果攻击状态时，即不能按按钮
		//判断一下，如果当前是攻击状态，即返回
		if (this.node._State != Common.State.IDLE) return;
		this._onButton = true;
		//判断按钮
		let name = e.target.name; //当前按钮的名字
		//点击按钮就播放跑步动画
		//这个是淡入动画，有一个过渡的动画，我在龙骨动画里，设定了0.1秒的时间
		let dir = name == "left" ? -1 : 1;
		dir = dir * 0.5

		let enemy = this.getEnemy();
		if (Common.checkCollide(this.node, enemy)) {
			//如果当前按钮与当前方向一样
			if (this._faceDir == dir) {
				this.attackAni();
			} else {
				this.dodge(dir);
			}

			return;
		}

		this._faceDir = dir;
		this._speed = this.moveSpeed * dir; //速度*方向


		let faceDir = new Vec2()
		this.node.getChildByName("body").getScale(faceDir)
		faceDir.x = -dir;

		this.node.getChildByName("body").setScale(faceDir);

		this.node._State = Common.State.MOVE; //把当前状态设为移动
		this.dbArmature.animation.fadeIn("move", -1, -1, 0, ANI_GROUP, dragonBones.AnimationFadeOutMode.All);
	}


	//闪避
	dodge(dir) {
		this.State = Common.State.DODGE;
		this.dbArmature.animation.fadeIn("avoid", -1, -1, 0, ANI_GROUP, dragonBones.AnimationFadeOutMode.All);
		// this.blackNode.active = true;



		// console.log(this.node.position,this.node.width)
		// 至边距的距离
		let len = Vec3.distance(this.node.position, new Vec3(this.boundary * dir, this.node.getPosition().y, this.node.getPosition().z));
		// 超出边界就按距离边界的距离闪避。防止跳到边界外
		len = len < this.ROLE.dodgeLen ? len : this.ROLE.dodgeLen;
		// 进行相对移动，执行完成之后进入静止状态
		tween(this.node)
			.by(0.2, { position: new Vec3(len * dir, 0, 0) })
			.call(() => {
				// this.blackNode.active = false;
				this.idleAni();
			})
			.start();


		Common.playAudio(Common.audioSource.flash,true,0.3)	

		// let len = this.node.width * dir;
		// console.log(len)
		// this.node.setPosition(new Vec3(this._curPos.x + len, this._curPos.y, this._curPos.z));
		// this.blackNode.active = false;
		// this.idleAni();

	}

	//取的敌人
	getEnemy() {
		this.enemyList = this.game.allEnemy;
		// console.log(this.enemyList)
		return this.enemyList[this._faceDir < 0 ? 0 : 1][0];
	}

	//触摸结束
	touchEnd(e) {
		this._onButton = false;//
		this._speed = 0; //如果放开按钮，我们就把速度设为0，那角动就不会再移动了
		if (this.node._State == Common.State.MOVE)


			this.idleAni(); //如果是移动状态，即播放待机画面  
	}
	//待机动画
	idleAni() {
		if (this.node.isDie) return;
		this.node._State = Common.State.IDLE;
		this.dbArmature.animation.fadeIn("idle", -1, -1, 0, ANI_GROUP, dragonBones.AnimationFadeOutMode.All);
	}

	//播放攻击动画
	attackAni() {
		if (this.node.isDie) return;
		this.node._State = Common.State.ATTACK;
		let attName = ATTANILIST[this.attCount]; //获得当前攻击动画的名称
		this.dbArmature.animation.fadeIn(attName, -1, -1, 0, ANI_GROUP);
		//下一个攻击动画的序号
		//攻击动画最大是3，如果大于3时，即返回第0个
		//如果attCount少于3，即+1， 如果大于等于3 ，即0;
		this.attCount = this.attCount < 3 ? this.attCount + 1 : 0;


		Common.playAudio(Common.audioSource.Attack,true,0.3);
	}

	//受到攻击
	uatt(att) {
		if (this.node.isDie) return;
		let hp = this.ROLE.hp - att;

		let pos = new Vec3()
		this.node.getPosition(pos);
		pos.y += this.node.height;
		this.game.showHit(att);
		// console.log(hp)
		if (hp <= 0) {



			this.node.isDie = true;
			this.offEvent(this.leftButton);
			this.offEvent(this.rightButton);
			this.setKeyBoard(false);
			this.dbDisplay.off(dragonBones.EventObject.COMPLETE, this.aniComplete, this);
			this.dbDisplay.off(dragonBones.EventObject.FRAME_EVENT, this.frameEvent, this);
			this.ROLE.hp = 0;
			this.hpBar.width = 0;
			this.dbDisplay.playAnimation("die");
			setTimeout(() => {
			
				director.loadScene("end")
			}, 1500);

			Common.playAudio(Common.audioSource.die_hero,true,0.3);
			return;
		}


		this.hpBar.width = (hp / this.ROLE.totalHp) * this.ROLE.hpW;
		this.ROLE.hp = hp;
		// console.log("hpbar",this.hpBar)
	}

	//移动
	move() {
		let enemy = this.getEnemy();
		// console.log(this.node.position)
		// 碰撞到怪物就自动攻击
		if (Common.checkCollide(this.node, enemy)) {
			// console.log(333)
			if ((this._faceDir < 0 && enemy.getPosition().x <= this.node.getPosition().x) || (this._faceDir > 0 && enemy.getPosition().x >= this.node.getPosition().x)) {
				this._speed = 0; //把当前速度降为0
				// console.log(333)
				this.attackAni();
				return;
			}
		}
		// 指定范围内移动
		if (this.node.getPosition().x > -this.boundary - this._speed && this.node.getPosition().x + this._speed < this.boundary) {
			this.node.getPosition(this._curPos);
			this._curPos.x = this._curPos.x + this._speed;
			this.node.setPosition(this._curPos);
			// console.log(this._curPos,this.boundary)
		}
	}



	// 刷新。会循环运行
	update(deltaTime: number) {
		//判断，当前速是否为0
		if (this.node.isDie) return;
		if (this._speed != 0) {
			this.move();
		}

	}
}

/**
 * [1] Class member could be defined like this.
 * [2] Use `property` decorator if your want the member to be serializable.
 * [3] Your initialization goes here.
 * [4] Your update function goes here.
 *
 * Learn more about scripting: https://docs.cocos.com/creator/3.0/manual/en/scripting/
 * Learn more about CCClass: https://docs.cocos.com/creator/3.0/manual/en/scripting/ccclass.html
 * Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.0/manual/en/scripting/life-cycle-callbacks.html
 */
